home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
051-075
/
disk_055
/
vt100
/
expand.c
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
9KB
|
355 lines
/*************************************************************
* vt100 terminal emulator - Wild card and Directory support
*
* v2.6 870227 DBW - bug fixes for all the stuff in v2.5
* v2.5 870214 DBW - more additions (see readme file)
* v2.4 861214 DBW - lots of fixes/additions (see readme file)
* v2.3 861101 DBW - minor bug fixes
* v2.2 861012 DBW - more of the same
* v2.1 860915 DBW - new features (see README)
* 860830 Steve Drew Added Wild card support,
* features(expand.c)
* v2.0 860809 DBW - Major rewrite
* v1.1 860720 DBW - Switches, 80 cols, colors, bug fixes
* v1.0 860712 DBW - First version released
*
* Much of the code from this module extracted from
* Matt Dillons Shell program. (Thanxs Matt.)
*************************************************************/
#include "vt100.h"
struct DPTR { /* Format of directory fetch ptr */
struct FileLock *lock; /* lock on directory */
struct FileInfoBlock *fib; /* mod'd fib for entry */
};
/*
* Disk directory routines
*
*
* diropen() returns a struct DPTR, or NULL if the given file does not
* exist. stat will be set to 1 if the file is a directory. If the
* name is "", then the current directory is openned.
*
* dirnext() returns 1 until there are no more entries. The **name and
* *stat are set. *stat = 1 if the file is a directory.
*
* dirclose() closes a directory channel.
*
*/
struct DPTR *
diropen(name, stat)
char *name;
int *stat;
{
struct DPTR *dp;
int namelen, endslash = 0;
struct FileLock *MyLock;
MyLock = (struct FileLock *)( (ULONG) ((struct Process *)
(FindTask(NULL)))->pr_CurrentDir);
namelen = strlen(name);
if (namelen && name[namelen - 1] == '/') {
name[namelen - 1] = '\0';
endslash = 1;
}
*stat = 0;
dp = (struct DPTR *)malloc(sizeof(struct DPTR));
if (*name == '\0')
dp->lock = (struct FileLock *)DupLock (MyLock);
else
dp->lock = (struct FileLock *)Lock (name, ACCESS_READ);
if (endslash)
name[namelen - 1] = '/';
if (dp->lock == NULL) {
free (dp);
return (NULL);
}
dp->fib = (struct FileInfoBlock *)
AllocMem((long)sizeof(struct FileInfoBlock), MEMF_PUBLIC);
if (!Examine (dp->lock, dp->fib)) {
dirclose (dp);
return (NULL);
}
if (dp->fib->fib_DirEntryType >= 0)
*stat = 1;
return (dp);
}
dirnext(dp, pname, stat)
struct DPTR *dp;
char **pname;
int *stat;
{
if (dp == NULL)
return (0);
if (ExNext (dp->lock, dp->fib)) {
*stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
*pname = dp->fib->fib_FileName;
return (1);
}
return (0);
}
dirclose(dp)
struct DPTR *dp;
{
if (dp == NULL)
return (1);
if (dp->fib)
FreeMem (dp->fib, (long)sizeof(*dp->fib));
if (dp->lock)
UnLock (dp->lock);
free (dp);
return (1);
}
free_expand(av)
char **av;
{
char **base = av;
if (av) {
while (*av) {
free (*av);
++av;
}
free (base);
}
}
/*
* EXPAND(wild_name, pac)
* wild_name - char * (example: "df0:*.c")
* pac - int * will be set to # of arguments.
*
*/
char **
expand(base, pac)
char *base;
int *pac;
{
char **eav = (char **)malloc (sizeof(char *));
int eleft, eac;
char *ptr, *name;
char *bname, *ename, *tail;
int stat, scr;
struct DPTR *dp;
*pac = eleft = eac = 0;
base = strcpy(malloc(strlen(base)+1), base);
for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
if (ptr < base) {
bname = strcpy (malloc(1), "");
} else {
scr = ptr[1];
ptr[1] = '\0';
bname = strcpy (malloc(strlen(base)+1), base);
ptr[1] = scr;
}
ename = ptr + 1;
for (ptr = ename; *ptr && *ptr != '/'; ++ptr);
scr = *ptr;
*ptr = '\0';
tail = (scr) ? ptr + 1 : NULL;
if ((dp = diropen (bname, &stat)) == NULL || stat == 0) {
free (bname);
free (base);
free (eav);
req ("Could not open directory","",0);
return (NULL);
}
while (dirnext (dp, &name, &stat)) {
if (compare_ok(ename, name)) {
if (tail) {
int alt_ac;
char *search, **alt_av, **scrav;
struct FileLock *lock;
if (!stat) /* expect more dirs, but this not a dir */
continue;
lock = (struct FileLock *)CurrentDir (dp->lock);
search = malloc(strlen(name)+strlen(tail)+2);
strcpy (search, name);
strcat (search, "/");
strcat (search, tail);
scrav = alt_av = expand (search, &alt_ac);
CurrentDir (lock);
if (scrav) {
while (*scrav) {
if (eleft < 2) {
char **scrav = (char **)
malloc(sizeof(char *) * (eac + 10));
movmem (eav, scrav, sizeof(char *) * (eac + 1));
free (eav);
eav = scrav;
eleft = 10;
}
eav[eac] = malloc(strlen(bname)+strlen(*scrav)+1);
strcpy(eav[eac], bname);
strcat(eav[eac], *scrav);
free (*scrav);
++scrav;
--eleft, ++eac;
}
free (alt_av);
}
} else {
if (eleft < 2) {
char **scrav = (char **)
malloc(sizeof(char *) * (eac + 10));
movmem (eav, scrav, sizeof(char *) * (eac + 1));
free (eav);
eav = scrav;
eleft = 10;
}
eav[eac] = malloc (strlen(bname)+strlen(name)+1);
eav[eac] = strcpy(eav[eac], bname);
strcat(eav[eac], name);
--eleft, ++eac;
}
}
}
dirclose (dp);
*pac = eac;
eav[eac] = NULL;
free (bname);
free (base);
if (eac)
return (eav);
free (eav);
return (NULL);
}
/*
* Compare a wild card name with a normal name
*/
#define MAXB 8
compare_ok(wild, name)
char *wild, *name;
{
char *w = wild;
char *n = name;
char *back[MAXB][2];
int bi = 0;
while (*n || *w) {
switch (*w) {
case '*':
if (bi == MAXB) {
req ("Too many levels of '*'","",0);
return (0);
}
back[bi][0] = w;
back[bi][1] = n;
++bi;
++w;
continue;
goback:
--bi;
while (bi >= 0 && *back[bi][1] == '\0')
--bi;
if (bi < 0)
return (0);
w = back[bi][0] + 1;
n = ++back[bi][1];
++bi;
continue;
case '?':
if (!*n) {
if (bi)
goto goback;
return (0);
}
break;
default:
if (toupper(*n) != toupper(*w)) {
if (bi)
goto goback;
return (0);
}
break;
}
if (*n) ++n;
if (*w) ++w;
}
return (1);
}
set_dir(new)
char *new;
{
register char *s;
int i;
struct FileLock *lock;
char temp[60];
struct FileInfoBlock *fib;
if (*new != '\000') {
strcpy(temp, MyDir);
s = new;
if (*s == '/') {
s++;
for (i=strlen(MyDir);
MyDir[i] != '/' && MyDir[i] != ':';
i--);
MyDir[i+1] = '\0';
strcat(MyDir, s);
}
else if (exists(s, ':') == 0) {
if (MyDir[strlen(MyDir)-1] != ':')
strcat(MyDir, "/");
strcat(MyDir, s);
}
else
strcpy(MyDir, s);
if ((lock = (struct FileLock *)Lock(MyDir, (long)ACCESS_READ)) == 0) {
req("Directory not found:",MyDir,0);
strcpy(MyDir, temp);
}
else {
fib = (struct FileInfoBlock *)AllocMem(
(long)sizeof(struct FileInfoBlock), MEMF_PUBLIC);
if (fib) {
if (Examine(lock, fib)) {
if (fib->fib_DirEntryType > 0) {
CurrentDir(lock);
if (MyDirLock != NULL) UnLock(MyDirLock);
MyDirLock = lock;
if (MyDir[strlen(MyDir)-1] == '/')
MyDir[strlen(MyDir)-1] = '\000';
}
else {
req("Not a Directory:",MyDir,0);
strcpy(MyDir,temp);
}
}
FreeMem(fib, (long)sizeof(struct FileInfoBlock));
}
else {
req("Can't change directory... ","No free memory!",0);
strcpy(MyDir,temp);
}
}
}
}
exists(s,c)
char *s,c;
{
while (*s != '\000')
if (*s++ == c) return(1);
return(0);
}